﻿using System;
using System.IO;
using System.Reflection;
using System.Xml.Serialization;
using SPS.Info.Collectors;
using SPS.Info.Models;

namespace SPS.Info
{
    /// <summary>
    /// Main application logic
    /// </summary>
    class Program
    {

        // Private members
        private static ServerFarm farm;

        /// <summary>
        /// Application entry point
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            Console.WriteLine();
            Console.WriteLine(Properties.Resources.ApplicationTitle, Assembly.GetExecutingAssembly().GetName().Version);
            Console.WriteLine();
            if (args.Length == 0 || args[0] == "-?" || args[0].ToLower() == "/h" || args[0].ToLower() == "-h")
                DisplayUsage();
            else
            {
                Console.WriteLine(string.Format(Constants.DisplayMessageFormat, DateTime.Now, Properties.Resources.StartDataCollection));
                Execute(Properties.Resources.FarmCollection, delegate() { farm = ServerFarmFactory.Collect(); });
                Execute(Properties.Resources.ServerCollection, delegate() { ServerNodeFactory.Collect(farm); });
                Execute(Properties.Resources.ServiceCollecion, delegate() { FarmServiceFactory.Collect(farm); });
                Execute(Properties.Resources.ProxyGroupsCollecion, delegate() { farm.ProxyGroups = ServiceApplicationProxyGroupFactory.Collect(); });
                Execute(Properties.Resources.SiteSubscriptionsCollecion, delegate() { farm.SiteSubscriptions = SiteSubscriptionFactory.Collect(); });
                Execute(Properties.Resources.TimerJobCollecion, delegate() { farm.TimerJobs = TimerJobFactory.Collect(); });
                Execute(Properties.Resources.SolutionCollecion, delegate() { farm.Solutions = SolutionFactory.Collect(); });
                Execute(Properties.Resources.FeatureCollecion, delegate() { farm.Features = FeatureFactory.Collect(); farm.ActiveFeatures = FeatureFactory.CollectActiveFarmFeatures(); });
                Execute(Properties.Resources.WebContentCollecion, delegate() { farm.WebApplications = WebApplicationFactory.Collect(); });
                Execute(Properties.Resources.ManagedAccountCollecion, delegate() { farm.ManagedAccounts = ManagedAccountFactory.Collect(); });
                Execute(Properties.Resources.HealthReportCollecion, delegate() { farm.HealthReports = HealthReportFactory.Collect(); });
                Execute(string.Format(Properties.Resources.SavingOutput, args[0]), delegate() { SerializeData(farm, args[0]); }, true);
                Console.WriteLine(string.Format(Constants.DisplayMessageFormat, DateTime.Now, Properties.Resources.EndDataCollection));
            }
            Environment.ExitCode = farm != null && (farm.Exceptions == null || farm.Exceptions.Count == 0) ? 0 : -1;
        }

        /// <summary>
        /// Display usage information
        /// </summary>
        private static void DisplayUsage()
        {
            Console.WriteLine(Properties.Resources.ApplicationUsage);
        }

        /// <summary>
        /// Execute operation
        /// </summary>
        /// <param name="message"></param>
        /// <param name="action"></param>
        private static void Execute(string message, Action action, bool displayException = false)
        {
            Console.Write(string.Format(Constants.DisplayMessageFormat, DateTime.Now, message));
            try
            {
                action.Invoke();
                Console.WriteLine(Properties.Resources.ExecutionCompleted);
            }
            catch (Exception ex)
            {
                Tools.LogException(farm, ex);
                if (displayException)
                    DisplayErrorMessage(string.Format(Properties.Resources.ExecutionErrorMessage, ex.Message));
                else
                    DisplayErrorMessage(Properties.Resources.ExecutionError);
            }
        }

        /// <summary>
        /// Save farm data to output file
        /// </summary>
        /// <param name="farm"></param>
        /// <param name="fileName"></param>
        private static void SerializeData(ServerFarm farm, string fileName)
        {
            using (TextWriter w = new StreamWriter(fileName))
            {
                XmlSerializer s = new XmlSerializer(farm.GetType());
                s.Serialize(w, farm);
            }
        }

        /// <summary>
        /// Display error message
        /// </summary>
        /// <param name="message"></param>
        private static void DisplayErrorMessage(string message)
        {
            ConsoleColor color = Console.ForegroundColor;
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine(message);
            Console.ForegroundColor = color;
        }

    }
}